import warnings
import geopandas
import libpysal
import momepy
import osmnx
import pandas
from clustergram import Clustergram
import matplotlib.pyplot as plt
from bokeh.io import output_notebook
from bokeh.plotting import showmaxvogt-analysis: Horgen
The code in this notebook is based on Martin Fleischmann’s 2021 workshop Capturing the Structure of Cities with Data Science (SDSC), licensed under the CC BY-SA 4.0 license. © 2021 Martin Fleischmann.
The geodata in this notebook is retrieved from OpenStreetMap. © OpenStreetMap Contributors.
This notebook contains geodata and analyses for the following items of the Max Vogt collection by Moritz Twente and Luisa Omonsky: - HG002 - SBG086
Open in an interactive in-browser environment:
Pick a place, ideally a town with a good coverage in OpenStreetMap and its local CRS.
place = 'Horgen'
local_crs = 'EPSG:2056'geopandas.tools.geocode(place).explore()Input data
Download data from OpenStreetMap.
Buildings
buildings = osmnx.features.features_from_place(place, tags={'building':True})/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:340: RuntimeWarning: invalid value encountered in union
return lib.union(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
buildings| ele | name | website | wikidata | wikipedia | geometry | man_made | tower:type | building | wheelchair | ... | fixme | contact:email | contact:website | internet_access | roof:cover:material | bicycle_parking | bike_ride | covered | ways | type | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| element_type | osmid | |||||||||||||||||||||
| node | 568617765 | NaN | Wohngruppe Spyrigarten | NaN | NaN | NaN | POINT (8.60652 47.21785) | NaN | NaN | public | yes | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 592412398 | NaN | NaN | NaN | NaN | NaN | POINT (8.55340 47.26518) | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| way | 23766001 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.57691 47.23839, 8.57696 47.23849, ... | NaN | NaN | service | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 23766008 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.57707 47.23870, 8.57714 47.23885, ... | NaN | NaN | train_station | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| 23766017 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.57749 47.24208, 8.57765 47.24212, ... | NaN | NaN | apartments | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| relation | 8709970 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.59923 47.25791, 8.59929 47.25789, ... | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [626332676, 32452892] | multipolygon |
| 9205904 | 420 | Bergwerk, Betriebsgebäude, Häuertreff | http://www.bergwerk-kaepfnach.ch/ | NaN | de:Bergwerk Käpfnach | POLYGON ((8.61135 47.25579, 8.61136 47.25581, ... | NaN | NaN | yes | no | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [97867696, 662290865] | multipolygon | |
| 9322011 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.61463 47.25497, 8.61470 47.25496, ... | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [97867656, 670167226] | multipolygon | |
| 9322263 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.61137 47.25582, 8.61137 47.25583, ... | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [667197110, 670191967] | multipolygon | |
| 11846798 | NaN | NaN | NaN | NaN | NaN | POLYGON ((8.59894 47.24960, 8.59894 47.24959, ... | NaN | NaN | yes | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | [32450402, 867971099] | multipolygon |
4407 rows × 103 columns
buildings.geom_type.value_counts()Polygon 4405
Point 2
Name: count, dtype: int64
buildings = buildings[buildings.geom_type == "Polygon"].reset_index(drop=True)buildings = buildings[["geometry"]].to_crs(local_crs)buildings["uID"] = range(len(buildings))buildings| geometry | uID | |
|---|---|---|
| 0 | POLYGON ((2686186.509 1232565.610, 2686189.629... | 0 |
| 1 | POLYGON ((2686198.118 1232600.536, 2686202.816... | 1 |
| 2 | POLYGON ((2686224.000 1232976.788, 2686236.026... | 2 |
| 3 | POLYGON ((2686041.467 1233166.544, 2686050.406... | 3 |
| 4 | POLYGON ((2686223.256 1233367.153, 2686232.653... | 4 |
| ... | ... | ... |
| 4400 | POLYGON ((2687844.074 1234760.243, 2687848.233... | 4400 |
| 4401 | POLYGON ((2688764.828 1234538.387, 2688765.590... | 4401 |
| 4402 | POLYGON ((2689014.197 1234451.155, 2689019.707... | 4402 |
| 4403 | POLYGON ((2688766.114 1234541.976, 2688766.389... | 4403 |
| 4404 | POLYGON ((2687835.257 1233836.065, 2687835.598... | 4404 |
4405 rows × 2 columns
Streets
In comparison to Martin Fleischmann’s workshop, I here set truncate_by_edge to be True. Depending on the OSM mapping quality of the place at hand, it might also be necessary to change the value of network_type. See geopandas documentation for options.
osm_graph = osmnx.graph_from_place(place, network_type='drive', truncate_by_edge=True)/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/constructive.py:181: RuntimeWarning: invalid value encountered in buffer
return lib.buffer(
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:340: RuntimeWarning: invalid value encountered in union
return lib.union(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/predicates.py:798: RuntimeWarning: invalid value encountered in intersects
return lib.intersects(a, b, **kwargs)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:340: RuntimeWarning: invalid value encountered in union
return lib.union(a, b, **kwargs)
osm_graph = osmnx.projection.project_graph(osm_graph, to_crs=local_crs)streets = osmnx.graph_to_gdfs(
osm_graph,
nodes=False,
edges=True,
node_geometry=False,
fill_edge_geometry=True
)streets.explore()streets| osmid | oneway | lanes | ref | highway | maxspeed | reversed | length | bridge | geometry | name | junction | access | width | tunnel | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| u | v | key | |||||||||||||||
| 453942 | 453966 | 0 | [660916013, 660916014, 306293043, 660920699, 6... | True | [3, 2] | A3 | motorway | 120 | False | 4230.315 | yes | LINESTRING (2685646.288 1236128.358, 2685699.1... | NaN | NaN | NaN | NaN | NaN |
| 453966 | 566185188 | 0 | 17281772 | True | 1 | 35 | motorway_link | 120 | False | 497.972 | NaN | LINESTRING (2688435.411 1232978.153, 2688511.2... | Horgen | NaN | NaN | NaN | NaN |
| 33980358 | 0 | [24228122, 17281836, 306293093] | True | 2 | A3 | motorway | 120 | False | 851.120 | yes | LINESTRING (2688435.411 1232978.153, 2688488.2... | NaN | NaN | NaN | NaN | NaN | |
| 566185188 | 566185191 | 0 | 5053172 | True | 1 | 341 | secondary | 60 | False | 11.659 | NaN | LINESTRING (2688746.582 1232602.634, 2688749.4... | Zugerstrasse | roundabout | NaN | NaN | NaN |
| 33980358 | 3111602950 | 0 | [306293100, 306293069, 117946996, 306293079, 3... | True | [3, 2] | A3 | motorway | 120 | False | 1432.115 | yes | LINESTRING (2689040.440 1232377.890, 2689089.4... | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 12157705083 | 12157705082 | 0 | 1313487776 | False | NaN | NaN | living_street | NaN | False | 10.469 | NaN | LINESTRING (2687026.113 1235323.933, 2687027.7... | NaN | NaN | NaN | NaN | NaN |
| 10795906516 | 0 | [1313487776, 702116462] | False | NaN | NaN | [living_street, residential] | 30 | [False, True] | 46.511 | NaN | LINESTRING (2687026.113 1235323.933, 2687039.4... | Asylstrasse | NaN | NaN | NaN | NaN | |
| 11224526888 | 471803170 | 0 | 9062655 | True | NaN | NaN | residential | 30 | False | 21.137 | NaN | LINESTRING (2688013.703 1234809.599, 2688024.9... | Schärbächlistrasse | NaN | NaN | NaN | NaN |
| 66819255 | 0 | 9065331 | True | NaN | NaN | residential | 30 | False | 75.982 | NaN | LINESTRING (2688013.703 1234809.599, 2688008.8... | Neudorfstrasse | NaN | NaN | NaN | NaN | |
| 11884166172 | 11884157862 | 0 | 1280243038 | False | NaN | NaN | residential | NaN | True | 208.318 | NaN | LINESTRING (2688629.670 1230091.835, 2688624.8... | Johanna-Spyri-Strasse | NaN | NaN | NaN | NaN |
1193 rows × 15 columns
streets = momepy.remove_false_nodes(streets)
streets = streets[["geometry"]]
streets["nID"] = range(len(streets))streets| geometry | nID | |
|---|---|---|
| 0 | LINESTRING (2685646.288 1236128.358, 2685699.1... | 0 |
| 1 | LINESTRING (2688435.411 1232978.153, 2688511.2... | 1 |
| 2 | LINESTRING (2688435.411 1232978.153, 2688488.2... | 2 |
| 3 | LINESTRING (2688746.582 1232602.634, 2688749.4... | 3 |
| 4 | LINESTRING (2689040.440 1232377.890, 2689089.4... | 4 |
| ... | ... | ... |
| 1068 | LINESTRING (2689993.139 1234038.390, 2690011.0... | 1068 |
| 1069 | LINESTRING (2689732.582 1229579.354, 2689743.0... | 1069 |
| 1070 | LINESTRING (2690192.670 1233561.272, 2690189.4... | 1070 |
| 1071 | LINESTRING (2690260.456 1231977.512, 2690230.7... | 1071 |
| 1072 | LINESTRING (2690351.446 1233218.259, 2690361.5... | 1072 |
1073 rows × 2 columns
Generated data
Tessellation
We can generate a spatail unit using Voronoi tessellation with given building footprints.
limit = momepy.buffered_limit(buildings, 100)
tessellation = momepy.Tessellation(buildings, "uID", limit, verbose=False, segment=1)
tessellation = tessellation.tessellation/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/constructive.py:181: RuntimeWarning: invalid value encountered in buffer
return lib.buffer(
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:426: RuntimeWarning: invalid value encountered in unary_union
return lib.unary_union(collections, **kwargs)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1328706492.py:3: FutureWarning: Class based API like `momepy.Tessellation` is deprecated. Replace it with `momepy.morphological_tessellation` or `momepy.enclosed_tessellation` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
tessellation = momepy.Tessellation(buildings, "uID", limit, verbose=False, segment=1)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/constructive.py:181: RuntimeWarning: invalid value encountered in buffer
return lib.buffer(
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:133: RuntimeWarning: invalid value encountered in intersection
return lib.intersection(a, b, **kwargs)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1328706492.py:3: UserWarning: Tessellation does not fully match buildings. 3 element(s) collapsed during generation - unique_id: {3579, 3580, 3581}.
tessellation = momepy.Tessellation(buildings, "uID", limit, verbose=False, segment=1)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1328706492.py:3: UserWarning: Tessellation contains MultiPolygon elements. Initial objects should be edited. `unique_id` of affected elements: [3320, 3321, 3322, 134, 3323, 3324, 3325, 3330, 3549, 3203, 1958, 3235, 3201, 4401, 3255, 4403, 1924, 3179, 3042].
tessellation = momepy.Tessellation(buildings, "uID", limit, verbose=False, segment=1)
Link streets
Link unique IDs of streets to buildings and tessellation cells based on the nearest neighbor join.
buildings = buildings.sjoin_nearest(streets, max_distance=1000, how="left")buildings| geometry | uID | index_right | nID | |
|---|---|---|---|---|
| 0 | POLYGON ((2686186.509 1232565.610, 2686189.629... | 0 | 253 | 253 |
| 1 | POLYGON ((2686198.118 1232600.536, 2686202.816... | 1 | 250 | 250 |
| 1 | POLYGON ((2686198.118 1232600.536, 2686202.816... | 1 | 253 | 253 |
| 2 | POLYGON ((2686224.000 1232976.788, 2686236.026... | 2 | 250 | 250 |
| 2 | POLYGON ((2686224.000 1232976.788, 2686236.026... | 2 | 253 | 253 |
| ... | ... | ... | ... | ... |
| 4402 | POLYGON ((2689014.197 1234451.155, 2689019.707... | 4402 | 124 | 124 |
| 4403 | POLYGON ((2688766.114 1234541.976, 2688766.389... | 4403 | 112 | 112 |
| 4403 | POLYGON ((2688766.114 1234541.976, 2688766.389... | 4403 | 116 | 116 |
| 4404 | POLYGON ((2687835.257 1233836.065, 2687835.598... | 4404 | 738 | 738 |
| 4404 | POLYGON ((2687835.257 1233836.065, 2687835.598... | 4404 | 390 | 390 |
6389 rows × 4 columns
buildings = buildings.drop_duplicates("uID").drop(columns="index_right")tessellation = tessellation.merge(buildings[['uID', 'nID']], on='uID', how='left')Measure
Measure individual morphometric characters.
Dimensions
buildings["area"] = buildings.area
tessellation["area"] = tessellation.area
streets["length"] = streets.lengthShape
buildings['eri'] = momepy.EquivalentRectangularIndex(buildings).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1902756608.py:1: FutureWarning: Class based API like `momepy.EquivalentRectangularIndex` is deprecated. Replace it with `momepy.equivalent_rectangular_index` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
buildings['eri'] = momepy.EquivalentRectangularIndex(buildings).series
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/pandas/core/arraylike.py:492: RuntimeWarning: invalid value encountered in oriented_envelope
return getattr(ufunc, method)(*new_inputs, **kwargs)
buildings['elongation'] = momepy.Elongation(buildings).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3723954296.py:1: FutureWarning: Class based API like `momepy.Elongation` is deprecated. Replace it with `momepy.elongation` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
buildings['elongation'] = momepy.Elongation(buildings).series
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/pandas/core/arraylike.py:492: RuntimeWarning: invalid value encountered in oriented_envelope
return getattr(ufunc, method)(*new_inputs, **kwargs)
tessellation['convexity'] = momepy.Convexity(tessellation).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/2335586521.py:1: FutureWarning: Class based API like `momepy.Convexity` is deprecated. Replace it with `momepy.convexity` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
tessellation['convexity'] = momepy.Convexity(tessellation).series
streets["linearity"] = momepy.Linearity(streets).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3802614628.py:1: FutureWarning: Class based API like `momepy.Linearity` is deprecated. Replace it with `momepy.linearity` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
streets["linearity"] = momepy.Linearity(streets).series
fig, ax = plt.subplots(1, 2, figsize=(24, 12))
buildings.plot("eri", ax=ax[0], scheme="natural_breaks", legend=True)
buildings.plot("elongation", ax=ax[1], scheme="natural_breaks", legend=True)
ax[0].set_title('Building Equivalent\nRectangular Index', fontsize=20)
ax[1].set_title('Building Elongation', fontsize=20)
ax[0].set_axis_off()
ax[1].set_axis_off()
plt.savefig('../results/Horgen/eri_and_elongation.svg') 
fig, ax = plt.subplots(1, 2, figsize=(24, 12))
tessellation.plot("convexity", ax=ax[0], scheme="natural_breaks", legend=True)
streets.plot("linearity", ax=ax[1], scheme="natural_breaks", legend=True)
ax[0].set_title('Convexity', fontsize=20)
ax[1].set_title('Linearity', fontsize=20)
ax[0].set_axis_off()
ax[1].set_axis_off()
plt.savefig('../results/Horgen/convexity_and_linearity.svg') 
Spatial distribution
buildings["shared_walls"] = momepy.SharedWallsRatio(buildings).series/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/momepy/distribution.py:214: FutureWarning: Class based API like `momepy.SharedWalls` or `momepy.SharedWallsRatio` is deprecated. Replace it with `momepy.shared_walls` or explicitly computing `momepy.shared_walls / gdf.length` respectively to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
super().__init__(gdf)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/set_operations.py:133: RuntimeWarning: invalid value encountered in intersection
return lib.intersection(a, b, **kwargs)
buildings.plot("shared_walls", figsize=(12, 12), scheme="natural_breaks", legend=True).set_axis_off()
plt.savefig('../results/Horgen/sharedwalls.svg') 
Generate spatial weights matrix using libpysal.
queen_1 = libpysal.weights.contiguity.Queen.from_dataframe(tessellation, ids="uID", silence_warnings=True)tessellation["neighbors"] = momepy.Neighbors(tessellation, queen_1, "uID", weighted=True, verbose=False).series
tessellation["covered_area"] = momepy.CoveredArea(tessellation, queen_1, "uID", verbose=False).series
with warnings.catch_warnings():
warnings.simplefilter("ignore")
buildings["neighbor_distance"] = momepy.NeighborDistance(buildings, queen_1, "uID", verbose=False).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1669107924.py:1: FutureWarning: Class based API like `momepy.Neighbors` is deprecated. Replace it with `momepy.neighbors` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
tessellation["neighbors"] = momepy.Neighbors(tessellation, queen_1, "uID", weighted=True, verbose=False).series
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1669107924.py:2: FutureWarning: `momepy.CoveredArea` is deprecated. Replace it with `.describe()` method of libpysal.graph.Graph or pin momepy version <1.0. This class will be removed in 1.0.
tessellation["covered_area"] = momepy.CoveredArea(tessellation, queen_1, "uID", verbose=False).series
fig, ax = plt.subplots(1, 2, figsize=(24, 12))
buildings.plot("neighbor_distance", ax=ax[0], scheme="natural_breaks", legend=True)
tessellation.plot("covered_area", ax=ax[1], scheme="natural_breaks", legend=True)
ax[0].set_title('Neighbour Distance', fontsize=20)
ax[1].set_title('Covered Area', fontsize=20)
ax[0].set_axis_off()
ax[1].set_axis_off()
plt.savefig('../results/Horgen/neighbourdist_and_coveredarea.svg') 
queen_3 = momepy.sw_high(k=3, weights=queen_1)
buildings_q1 = libpysal.weights.contiguity.Queen.from_dataframe(buildings, silence_warnings=True)
buildings['interbuilding_distance'] = momepy.MeanInterbuildingDistance(buildings, queen_1, 'uID', queen_3, verbose=False).series
buildings['adjacency'] = momepy.BuildingAdjacency(buildings, queen_3, 'uID', buildings_q1, verbose=False).series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3221532125.py:1: FutureWarning: `momepy.sw_high` is deprecated. Replace it with .higher_order() method of libpysal.graph.Graph or pin momepy version <1.0. This class will be removed in 1.0.
queen_3 = momepy.sw_high(k=3, weights=queen_1)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3221532125.py:2: FutureWarning: `use_index` defaults to False but will default to True in future. Set True/False directly to control this behavior and silence this warning
buildings_q1 = libpysal.weights.contiguity.Queen.from_dataframe(buildings, silence_warnings=True)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3221532125.py:4: FutureWarning: Class based API like `momepy.MeanInterbuildingDistance` is deprecated. Replace it with `momepy.mean_interbuilding_distance` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
buildings['interbuilding_distance'] = momepy.MeanInterbuildingDistance(buildings, queen_1, 'uID', queen_3, verbose=False).series
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/shapely/measurement.py:74: RuntimeWarning: invalid value encountered in distance
return lib.distance(a, b, **kwargs)
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/3221532125.py:5: FutureWarning: Class based API like `momepy.BuildingAdjacency` is deprecated. Replace it with `momepy.building_adjacency` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
buildings['adjacency'] = momepy.BuildingAdjacency(buildings, queen_3, 'uID', buildings_q1, verbose=False).series
#fig, ax = plt.subplots(1, 2, figsize=(24, 12))
#
#buildings.plot("interbuilding_distance", ax=ax[0], scheme="natural_breaks", legend=True)
#buildings.plot("adjacency", ax=ax[1], scheme="natural_breaks", legend=True)
#
#ax[0].set_axis_off()
#ax[1].set_axis_off()profile = momepy.StreetProfile(streets, buildings)
streets["width"] = profile.w
streets["width_deviation"] = profile.wd
streets["openness"] = profile.o/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/2648127835.py:1: FutureWarning: Class based API like `momepy.StreetProfile` is deprecated. Replace it with `momepy.street_profile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
profile = momepy.StreetProfile(streets, buildings)
/Users/mtwente/anaconda3/envs/maxvogt/lib/python3.11/site-packages/pandas/core/arraylike.py:492: RuntimeWarning: invalid value encountered in intersection
return getattr(ufunc, method)(*new_inputs, **kwargs)
fig, ax = plt.subplots(1, 3, figsize=(24, 12))
streets.plot("width", ax=ax[0], scheme="natural_breaks", legend=True)
streets.plot("width_deviation", ax=ax[1], scheme="natural_breaks", legend=True)
streets.plot("openness", ax=ax[2], scheme="natural_breaks", legend=True)
ax[0].set_title('Width', fontsize=20)
ax[1].set_title('Width Deviation', fontsize=20)
ax[2].set_title('Openness', fontsize=20)
ax[0].set_axis_off()
ax[1].set_axis_off()
ax[2].set_axis_off()
plt.savefig('../results/Horgen/road_network.svg') 
Intensity
tessellation['car'] = momepy.AreaRatio(tessellation, buildings, 'area', 'area', 'uID').series/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/1819725789.py:1: FutureWarning: `momepy.AreaRatio` is deprecated. Replace it with a direct division of areas or momepy.describe_agg() or pin momepy version <1.0. This class will be removed in 1.0.
tessellation['car'] = momepy.AreaRatio(tessellation, buildings, 'area', 'area', 'uID').series
tessellation.plot("car", figsize=(12, 12), vmin=0, vmax=1, legend=True).set_axis_off()
plt.title("Building/Tessellation Area Ratio")
plt.savefig('../results/Buchs/tessellation_ratio.svg') 
Connectivity
graph = momepy.gdf_to_nx(streets)graph = momepy.node_degree(graph)
graph = momepy.closeness_centrality(graph, radius=400, distance="mm_len")
graph = momepy.meshedness(graph, radius=400, distance="mm_len")nodes, streets = momepy.nx_to_gdf(graph)fig, ax = plt.subplots(1, 3, figsize=(24, 12))
nodes.plot("degree", ax=ax[0], scheme="natural_breaks", legend=True, markersize=1)
nodes.plot("closeness", ax=ax[1], scheme="natural_breaks", legend=True, markersize=1, legend_kwds={"fmt": "{:.6f}"})
nodes.plot("meshedness", ax=ax[2], scheme="natural_breaks", legend=True, markersize=1)
ax[0].set_axis_off()
ax[1].set_axis_off()
ax[2].set_axis_off()
plt.savefig('../results/Horgen/connectivity.svg') 
buildings["nodeID"] = momepy.get_node_id(buildings, nodes, streets, "nodeID", "nID")/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/403706460.py:1: FutureWarning: Class based API like `momepy.get_node_id` is deprecated. Replace it with `momepy.get_nearest_node` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
buildings["nodeID"] = momepy.get_node_id(buildings, nodes, streets, "nodeID", "nID")
Link all data together (to tessellation cells or buildings).
tessellation| uID | geometry | nID | area | convexity | neighbors | covered_area | car | |
|---|---|---|---|---|---|---|---|---|
| 0 | 3899 | POLYGON ((2689319.058 1228502.785, 2689319.373... | 909 | 13536.968857 | 0.999685 | 0.002196 | 40591.707399 | 0.001398 |
| 1 | 2519 | POLYGON ((2689877.834 1229266.445, 2689878.299... | 1067 | 14206.747812 | 0.971804 | 0.002107 | 38576.168129 | 0.008151 |
| 2 | 2550 | POLYGON ((2689503.117 1228802.495, 2689502.828... | 231 | 17390.268825 | 0.995609 | 0.003911 | 69629.139769 | 0.007822 |
| 3 | 2552 | POLYGON ((2689455.083 1228900.881, 2689453.879... | 231 | 28673.263230 | 0.997154 | 0.004734 | 83935.908790 | 0.004550 |
| 4 | 2553 | POLYGON ((2689582.424 1229277.091, 2689583.224... | 236 | 40005.075688 | 0.998041 | 0.004150 | 80999.264679 | 0.016470 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4397 | 3567 | POLYGON ((2684418.216 1236283.851, 2684417.790... | 951 | 3517.037790 | 0.741056 | 0.009379 | 24418.652313 | 0.026464 |
| 4398 | 3168 | POLYGON ((2684517.058 1236218.230, 2684516.937... | 951 | 16446.356915 | 0.984527 | 0.012133 | 53586.974197 | 0.028138 |
| 4399 | 1077 | POLYGON ((2686636.264 1236016.009, 2686635.376... | 385 | 13928.036878 | 0.991460 | 0.008741 | 21846.889918 | 0.018775 |
| 4400 | 3058 | POLYGON ((2684352.774 1236379.668, 2684340.129... | 951 | 26998.373794 | 0.997732 | 0.001617 | 38883.381637 | 0.003054 |
| 4401 | 3059 | POLYGON ((2684438.083 1236281.038, 2684437.746... | 951 | 7648.509071 | 0.997930 | 0.011688 | 33532.051510 | 0.001875 |
4402 rows × 8 columns
merged = tessellation.merge(buildings.drop(columns=['nID', 'geometry']), on='uID')
merged = merged.merge(streets.drop(columns='geometry'), on='nID', how='left')
merged = merged.merge(nodes.drop(columns='geometry'), on='nodeID', how='left')merged.columnsIndex(['uID', 'geometry', 'nID', 'area_x', 'convexity', 'neighbors',
'covered_area', 'car', 'area_y', 'eri', 'elongation', 'shared_walls',
'neighbor_distance', 'interbuilding_distance', 'adjacency', 'nodeID',
'length', 'linearity', 'width', 'width_deviation', 'openness', 'mm_len',
'node_start', 'node_end', 'x', 'y', 'degree', 'closeness',
'meshedness'],
dtype='object')
Understanding the context
Measure first, second and third quartile of distribution of values within an area around each building.
percentiles = []
for column in merged.columns.drop(["uID", "nodeID", "nID", 'mm_len', 'node_start', 'node_end', "geometry"]):
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
perc.columns = [f"{column}_" + str(x) for x in perc.columns]
percentiles.append(perc)/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
/var/folders/vs/1r1r5k5x12v5dj0w9z79tj3c0000gn/T/ipykernel_17680/962013058.py:3: FutureWarning: Class based API like `momepy.Percentiles` is deprecated. Replace it with `momepy.percentile` to use functional API instead or pin momepy version <1.0. Class-based API will be removed in 1.0.
perc = momepy.Percentiles(merged, column, queen_3, "uID", verbose=False).frame
percentiles_joined = pandas.concat(percentiles, axis=1)percentiles_joined| area_x_25 | area_x_50 | area_x_75 | convexity_25 | convexity_50 | convexity_75 | neighbors_25 | neighbors_50 | neighbors_75 | covered_area_25 | ... | y_75 | degree_25 | degree_50 | degree_75 | closeness_25 | closeness_50 | closeness_75 | meshedness_25 | meshedness_50 | meshedness_75 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 20295.853700 | 20295.853700 | 20295.853700 | 0.926016 | 0.926016 | 0.926016 | 0.001830 | 0.001830 | 0.001830 | 40591.707399 | ... | 1.229059e+06 | 6.0 | 6.0 | 6.0 | 0.000041 | 0.000041 | 0.000041 | 1.285714 | 1.285714 | 1.285714 |
| 1 | 8312.384337 | 13893.159983 | 29750.383925 | 0.976395 | 0.988553 | 0.994496 | 0.004256 | 0.005333 | 0.015039 | 62877.036349 | ... | 1.229563e+06 | 2.5 | 4.0 | 5.5 | 0.000005 | 0.000032 | 0.000063 | -0.000000 | 0.400000 | 0.428571 |
| 2 | 12678.932766 | 14306.769020 | 21814.991149 | 0.913928 | 0.975653 | 0.995598 | 0.004804 | 0.005887 | 0.009185 | 60535.816244 | ... | 1.229191e+06 | 4.0 | 6.0 | 6.0 | 0.000000 | 0.000041 | 0.000059 | 0.000000 | 0.909091 | 1.285714 |
| 3 | 7971.941841 | 13119.079225 | 16687.462905 | 0.911438 | 0.976800 | 0.994006 | 0.005394 | 0.009645 | 0.014407 | 41491.483420 | ... | 1.229191e+06 | 6.0 | 6.0 | 6.0 | 0.000041 | 0.000059 | 0.000059 | 0.909091 | 0.909091 | 1.097403 |
| 4 | 1250.221776 | 2625.603244 | 8371.837168 | 0.943774 | 0.969071 | 0.983559 | 0.015141 | 0.022922 | 0.033719 | 17771.773612 | ... | 1.229546e+06 | 1.0 | 5.0 | 5.5 | 0.000041 | 0.000051 | 0.000067 | 0.400000 | 0.555556 | 0.555556 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4397 | 3062.904136 | 7478.348459 | 13197.316837 | 0.918197 | 0.983055 | 0.992881 | 0.009690 | 0.013852 | 0.016316 | 34580.621922 | ... | 1.236327e+06 | 1.0 | 1.0 | 1.0 | 0.000000 | 0.000000 | 0.000000 | -0.000000 | -0.000000 | -0.000000 |
| 4398 | 3676.395892 | 6707.813043 | 11252.852991 | 0.943990 | 0.959093 | 0.988009 | 0.009690 | 0.013428 | 0.016318 | 35423.593686 | ... | 1.236327e+06 | 1.0 | 1.0 | 5.0 | 0.000000 | 0.000000 | 0.000024 | -0.000000 | -0.000000 | 2.000000 |
| 4399 | 462.725229 | 1392.490924 | 2392.734452 | 0.898778 | 0.955623 | 0.989855 | 0.016694 | 0.041426 | 0.068439 | 8624.710343 | ... | 1.236018e+06 | 4.0 | 5.0 | 6.0 | 0.000025 | 0.000042 | 0.000042 | 0.857143 | 0.857143 | 1.000000 |
| 4400 | 4034.543958 | 7478.348459 | 11200.428376 | 0.918197 | 0.964269 | 0.996001 | 0.008701 | 0.010844 | 0.016316 | 34580.621922 | ... | 1.236327e+06 | 1.0 | 1.0 | 1.0 | 0.000000 | 0.000000 | 0.000000 | -0.000000 | -0.000000 | -0.000000 |
| 4401 | 4552.050125 | 7648.509071 | 11704.140047 | 0.944098 | 0.982650 | 0.994270 | 0.008703 | 0.011688 | 0.015752 | 35629.192334 | ... | 1.236327e+06 | 1.0 | 1.0 | 5.0 | 0.000000 | 0.000000 | 0.000024 | 0.000000 | 0.000000 | 2.000000 |
4402 rows × 66 columns
fig, ax = plt.subplots(1, 2, figsize=(24, 12))
tessellation.plot("convexity", ax=ax[0], scheme="natural_breaks", legend=True)
merged.plot(percentiles_joined['convexity_50'].values, ax=ax[1], scheme="natural_breaks", legend=True)
ax[0].set_title('Convexity', fontsize=20)
ax[1].set_title('Convexity_50', fontsize=20)
ax[0].set_axis_off()
ax[1].set_axis_off()
plt.savefig('../results/Horgen/convexity.svg') 
Clustering
Standardize values before clustering.
standardized = (percentiles_joined - percentiles_joined.mean()) / percentiles_joined.std()standardized| area_x_25 | area_x_50 | area_x_75 | convexity_25 | convexity_50 | convexity_75 | neighbors_25 | neighbors_50 | neighbors_75 | covered_area_25 | ... | y_75 | degree_25 | degree_50 | degree_75 | closeness_25 | closeness_50 | closeness_75 | meshedness_25 | meshedness_50 | meshedness_75 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 5.964129 | 4.489802 | 2.971976 | 0.147309 | -2.050268 | -4.838937 | -1.944423 | -2.249626 | -2.466641 | 2.233410 | ... | -2.444281 | 1.135398 | 0.703586 | 0.320717 | -0.587106 | -0.818632 | -0.994063 | 1.155988 | 0.943902 | 0.739740 |
| 1 | 2.145222 | 2.851285 | 4.769267 | 2.340401 | 2.256864 | 1.774134 | -1.771262 | -2.030680 | -1.757687 | 4.043226 | ... | -2.174389 | -0.712788 | -0.739482 | -0.167963 | -1.131420 | -0.945250 | -0.744876 | -0.688147 | -0.300631 | -0.403002 |
| 2 | 3.536759 | 2.957132 | 3.260761 | -0.378915 | 1.368420 | 1.880554 | -1.732157 | -1.996012 | -2.071872 | 3.853093 | ... | -2.373496 | 0.079292 | 0.703586 | 0.320717 | -1.207278 | -0.818632 | -0.791357 | -0.688147 | 0.414701 | 0.739740 |
| 3 | 2.036729 | 2.653190 | 2.286026 | -0.487309 | 1.447428 | 1.726819 | -1.690036 | -1.761195 | -1.791604 | 2.306482 | ... | -2.373496 | 1.135398 | 0.703586 | 0.320717 | -0.587106 | -0.594654 | -0.791357 | 0.615787 | 0.414701 | 0.488683 |
| 4 | -0.105357 | -0.032202 | 0.705238 | 0.920354 | 0.915060 | 0.718000 | -0.994383 | -0.931319 | -0.755058 | 0.380178 | ... | -2.183213 | -1.504867 | -0.017948 | -0.167963 | -0.588328 | -0.697673 | -0.698258 | -0.114416 | -0.082057 | -0.233707 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 4397 | 0.472311 | 1.209667 | 1.622555 | -0.193087 | 1.878239 | 1.618188 | -1.383412 | -1.498203 | -1.689119 | 1.745243 | ... | 1.449723 | -1.504867 | -2.904084 | -4.566089 | -1.207278 | -1.355241 | -1.479710 | -0.688147 | -0.862679 | -0.974373 |
| 4398 | 0.667819 | 1.012479 | 1.252915 | 0.929731 | 0.227862 | 1.147742 | -1.383412 | -1.524727 | -1.689026 | 1.813702 | ... | 1.449723 | -1.504867 | -2.904084 | -0.656644 | -1.207278 | -1.355241 | -1.196904 | -0.688147 | -0.862679 | 1.692024 |
| 4399 | -0.356317 | -0.347769 | -0.431380 | -1.038443 | -0.011123 | 1.326029 | -0.883526 | 0.225139 | 1.108394 | -0.362665 | ... | 1.283781 | 0.079292 | -0.017948 | 0.320717 | -0.835819 | -0.810453 | -0.986661 | 0.541276 | 0.341708 | 0.358826 |
| 4400 | 0.781954 | 1.209667 | 1.242949 | -0.193087 | 0.584331 | 1.919509 | -1.453998 | -1.686205 | -1.689119 | 1.745243 | ... | 1.449723 | -1.504867 | -2.904084 | -4.566089 | -1.207278 | -1.355241 | -1.479710 | -0.688147 | -0.862679 | -0.974373 |
| 4401 | 0.946874 | 1.253213 | 1.338704 | 0.934465 | 1.850354 | 1.752384 | -1.453835 | -1.633493 | -1.719419 | 1.830399 | ... | 1.449723 | -1.504867 | -2.904084 | -0.656644 | -1.207278 | -1.355241 | -1.196904 | -0.688147 | -0.862679 | 1.692024 |
4402 rows × 66 columns
How many clusters?
cgram = Clustergram(range(1, 12), n_init=10, random_state=0)
cgram.fit(standardized.fillna(0))K=1 skipped. Mean computed from data directly.
K=2 fitted in 0.039 seconds.
K=3 fitted in 0.048 seconds.
K=4 fitted in 0.064 seconds.
K=5 fitted in 0.069 seconds.
K=6 fitted in 0.127 seconds.
K=7 fitted in 0.077 seconds.
K=8 fitted in 0.074 seconds.
K=9 fitted in 0.089 seconds.
K=10 fitted in 0.085 seconds.
K=11 fitted in 0.101 seconds.
Clustergram(k_range=range(1, 12), backend='sklearn', method='kmeans', kwargs={'n_init': 10, 'random_state': 0})
show(cgram.bokeh())cgram.labels.head()| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 1 | 3 | 3 | 3 | 0 | 5 | 0 | 5 | 7 |
| 1 | 0 | 0 | 1 | 3 | 2 | 4 | 0 | 5 | 0 | 5 | 7 |
| 2 | 0 | 0 | 1 | 3 | 2 | 4 | 0 | 5 | 0 | 5 | 7 |
| 3 | 0 | 0 | 1 | 3 | 2 | 4 | 2 | 2 | 4 | 2 | 2 |
| 4 | 0 | 0 | 1 | 0 | 4 | 1 | 4 | 6 | 5 | 1 | 3 |
merged["cluster"] = cgram.labels[8].valuesurban_types = buildings[["geometry", "uID"]].merge(merged[["uID", "cluster"]], on="uID")urban_types.explore("cluster", categorical=True, prefer_canvas=True, tiles="CartoDB Positron", tooltip=False)Export
Save cluster output geodata to geojson file:
urban_types.to_file('../data/raw/Horgen.geojson', driver='GeoJSON')Utilities
Once you run the cell below, it hides all cells below the currently active one (aka presentation mode).
%%html
<style>
.jp-Cell.jp-mod-selected ~ .jp-Cell {
display: none;
}
</style>Run this cell to turn the presentation mode off.
%%html
<style>
.jp-Cell.jp-mod-selected ~ .jp-Cell {
display: block;
}
</style>